package tx.oopa.circuit.port;

import java.io.File;
import java.io.FilenameFilter;
import java.util.Hashtable;

/**
 * The PortFactory handles the instantation of the correct component by the
 * given identifier.
 * 
 * @author Xander van Rijn
 *
 */
public final class PortFactory {

    private static PortFactory instance = null;
    private Hashtable<String, AbstractComponent> idTable;

    private PortFactory() {
        idTable = new Hashtable<String, AbstractComponent>();
    }

    public static PortFactory getInstance() {
        if (instance == null) {
            instance = new PortFactory();
            initialize();
        }
        return instance;
    }

    /**
     * Returns an instance of the component related to the identifier.
     * Null will be returned if the identifier is not recognized.
     * 
     * @param identifier Identifier of a component
     * @return Instance of a component or null if not found
     */
    public static AbstractComponent createComponent(String identifier) {
        AbstractComponent component = getInstance().idTable.get(identifier);

        if (component == null) {
            return null;
        }
        else {
            return component.clone();
        }
    }

    /**
     * Adds a component to the list of possible components by identifier.
     * 
     * @param ID Identifier of the component
     * @param component The component itself
     */
    public static void assign(String ID, AbstractComponent component) {
        if (ID != null && !ID.isEmpty()) {
            getInstance().idTable.put(ID, component);
        }
    }

    private static void initialize() {
        String dir = getDirectory();
        loadClasses(dir);
    }

    private static String getDirectory() {
        String sAllDirs = System.getProperty("java.class.path");
        String sSepWith = System.getProperty("path.separator");
        int nSize = sAllDirs.indexOf(sSepWith);

        if (nSize < 0) {
            return sAllDirs + "\\tx\\oopa\\circuit\\port\\impl";
        }
        else {
            return sAllDirs.substring(0, nSize) + "\\tx\\oopa\\circuit\\port\\impl";
        }
    }

    private static void loadClasses( String sDir ) {
        try {
            if ( sDir != null ) {
                File file   = new File(sDir);
                FilenameFilter filter = new ClassFilenameFilter();
                String[] list = file.list(filter);
                int nSize;
                String name;

                for ( int n=0; n<list.length; n++ ) {
                    nSize = list[n].indexOf( '.' );
                    name = "tx.oopa.circuit.port.impl." + list[n].substring( 0, nSize );
                    Class.forName( name );
                }
            }
        } catch( Exception e ) {
            e.printStackTrace();
        }
    }
}
